<template>
  <div class="color-view" ref="currentRef" :class="{ 'is-warning': computeAppend && allowAppend, 'is-highlight': !computeAppend && publicState.active === color }">
    <div class="color-box"></div>
    <div class="color-preview">
      <div class="color-preview__alias">{{ aliasValue ?? '-' }}</div>
      <div class="color-preview__value">{{ color }}</div>
    </div>
    <div class="color-tools">
      <el-tooltip :append-to="rootRef" :content="aliasValue ? '编辑别名' : '设置别名'" v-if="!allowAppend">
        <el-icon @click="onAlias"><IconEdit /></el-icon>
      </el-tooltip>
      <el-tooltip :append-to="rootRef" content="记录" v-if="allowAppend">
        <el-icon @click="onAppend(color, true)"><IconSelect /></el-icon>
      </el-tooltip>
      <el-tooltip :append-to="rootRef" content="取消记录" v-if="!computeAppend && !allowAppend">
        <el-icon @click="onUnappend(color)"><IconSemiSelect /></el-icon>
      </el-tooltip>
      <el-tooltip :append-to="rootRef" content="移除" v-if="!computeAppend || !allowAppend">
        <el-icon @click="onRemove(color)"><IconCloseBold /></el-icon>
      </el-tooltip>
      <el-tooltip :append-to="rootRef" content="复制值">
        <el-icon @click="onCopy(color)"><IconCopyDocument /></el-icon>
      </el-tooltip>
      <el-tooltip :append-to="rootRef" content="复制别名" v-if="aliasValue">
        <el-icon @click="onCopy(aliasValue)"><IconCopyDocument /></el-icon>
      </el-tooltip>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { Edit as IconEdit, CloseBold as IconCloseBold, CopyDocument as IconCopyDocument, Select as IconSelect, SemiSelect as IconSemiSelect } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { computed, h, type CSSProperties, Fragment, ref, watch, onMounted } from 'vue'
import tinycolor from 'tinycolor2'
import { useColorStore } from '@/inject/stores/color'
import { useAppInject } from '../InjectApp'
import { colorPrefix, colorSpaceAlias, getHue, setColorAlias } from '@/shared/color'
import { logError } from '@/shared/utils'

defineOptions({ name: 'ColorView' })

const props = defineProps<{ color: string; append?: boolean; computeAppend?: boolean }>()

const { publicState, copy, append: onAppend, unappend: onUnappend, remove: onRemove } = useColorStore()

const allowAppend = computed(() => {
  const { append, computeAppend, color } = props

  if (!computeAppend) return append

  const { object } = publicState

  if (!object) return false
  const { confirmed, unconfirmed } = object
  if (unconfirmed.includes(props.color)) return true

  const list = confirmed[getHue(tinycolor(color))]

  if (list && list.includes(color)) return false

  return true
})

const aliasValue = computed(() => {
  const { object } = publicState
  if (!object) return
  const prefix = colorPrefix[object.vartype]
  const name = colorSpaceAlias(object, props.color, true)
  return name && `${prefix}${name}`
})

const currentRef = ref<HTMLDivElement>()

function onScroll() {
  if (publicState.active === props.color) {
    currentRef.value?.scrollIntoView({ block: 'start', behavior: 'smooth' })
  }
}

watch([() => publicState.active, () => props.color], onScroll)

onMounted(onScroll)

const { rootRef } = useAppInject()

function onCopy(value?: string) {
  value &&
    copy(value).then(() => {
      ElMessage({
        type: 'success',
        message: '已复制',
        appendTo: rootRef.value
      })
    })
}

function onAlias() {
  const { color } = props
  ElMessageBox.prompt(
    () => {
      const style: CSSProperties = {
        display: 'inline-block',
        width: '12px',
        height: '12px',
        background: color,
        marginRight: '5px'
      }
      return h(Fragment, [h('span', { style }), color])
    },
    {
      confirmButtonText: '确认',
      cancelButtonText: '取消',
      appendTo: rootRef.value,
      overflow: true,
      inputPlaceholder: `请输入别名，为空将清除之前的别名`,
      inputPattern: /^[a-zA-Z0-9-_]{0,20}$/,
      inputErrorMessage: '请输入 字母、数字、-、_ 组成的 0~20 长度的字符串',
      customStyle: { width: '320px' },
      lockScroll: false
    }
  ).then(({ value }) => {
    setColorAlias(publicState.object, color, value)
  }, logError)
}
</script>

<style lang="scss" scoped>
.color-view {
  min-width: 90px;
  display: inline-block;
  position: relative;
  background-color: #e7e7e7;
  border-radius: 2px;
  font-size: 10px;
  padding: 5px;
  display: flex;
  column-gap: 5px;
  align-items: center;
  overflow: hidden;

  &.is-warning {
    background: rgba(255, 199, 199, 0.5);
    box-shadow: 0px 0 3px 0px rgb(255 0 0 / 50%);
  }

  &.is-highlight {
    background: #0080001a;
    box-shadow: 0px 0 3px 0px #008000;
  }
}

.color-box {
  width: 22px;
  height: 22px;
  border-radius: 2px;
  background: url();
  box-shadow: 0 0 1px 1px #a5a5a5;

  &::before {
    content: '';
    display: block;
    width: 100%;
    height: 100%;
    background-color: v-bind(color);
  }
}

.color-preview {
  flex: 1;
  display: flex;
  align-items: flex-start;
  column-gap: 10px;
  box-sizing: border-box;
  flex-direction: column;
  justify-content: center;
  line-height: 1;
  gap: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;

  .color-preview__alias {
    color: #73737380;
  }

  .color-preview__value {
    color: #737373b3;
    text-shadow: 0 0 #a5a5a5;
  }
}

.color-tools {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  column-gap: 10px;
  background-color: rgb(65 65 65 / 70%);
  box-sizing: border-box;
  padding: 0 5px;
  visibility: hidden;
  border-radius: 2px;

  :deep(.el-icon) {
    cursor: pointer;
  }
}

.color-view:hover .color-tools {
  visibility: visible;

  :deep(.el-icon) {
    color: #fff;

    &:hover {
      transform: scale(1.1);
      color: rgb(0, 180, 0);
    }
  }
}
</style>
